package com.netty.demo.udp;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.util.CharsetUtil;
import io.netty.util.NetUtil;

/**
 * UPD组播 Client
 *
 * @author zhangtao
 */
public class MultiCastClient {

    public static void main(String[] args) {
        System.setProperty("java.net.preferIPv4Stack", "true");

        // 组播地址
        InetSocketAddress groupAddress = new InetSocketAddress("224.2.1.1", 9000);
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            NetworkInterface ni = NetUtil.LOOPBACK_IF;
            Enumeration<InetAddress> addresses = ni.getInetAddresses();
            InetAddress localAddress = null;
            while (addresses.hasMoreElements()) {
                InetAddress address = addresses.nextElement();
                if (address instanceof Inet4Address) {
                    localAddress = address;
                }
            }

            Bootstrap b = new Bootstrap();
            // 设置Channel
            b.group(group)
                    .channel(NioDatagramChannel.class)
                    // 设置LocalAddress
                    .localAddress(localAddress, groupAddress.getPort())
                    // 设置Option 组播
                    .option(ChannelOption.IP_MULTICAST_IF, ni)
                    // 设置Option 重复地址
                    .option(ChannelOption.SO_REUSEADDR, true)
                    // 设置Handler
                    .handler(new ChannelInitializer<NioDatagramChannel>() {

                        @Override
                        protected void initChannel(NioDatagramChannel ch) throws Exception {
                            ch.pipeline().addLast(new SimpleChannelInboundHandler<DatagramPacket>() {

                                @Override
                                protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg)
                                        throws Exception {
                                    // 打印一句话
                                    System.out.println(msg.content().toString(CharsetUtil.UTF_8));
                                }
                            });
                        }
                    });

            // 获取Channel
            Channel ch = b.bind().sync().channel();
            // 往组播地址中发送数据报
            ch.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer("hello world", CharsetUtil.UTF_8), groupAddress))
                    .sync();// 发送数据

            // 关闭Channel
            ch.close().awaitUninterruptibly();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            group.shutdownGracefully();
        }
    }
}
